package com.itheima.datastructure.blockingqueue;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/*
阻塞队列：双锁实现
 */
public class BlockingQueue2<E> implements BlockingQueue<E>{

    private final E[] array;
    private int head;
    private int tail;
    //保持size的原子一致性
    private AtomicInteger size=new AtomicInteger();
    private ReentrantLock tailLock=new ReentrantLock();
    private Condition tailWaits= tailLock.newCondition();
    private ReentrantLock headLock=new ReentrantLock();
    private Condition headWaits= headLock.newCondition();

    public BlockingQueue2(int capacity) {
        this.array = (E[])new Object[capacity];
    }

    private boolean isEmpty(){
        return size.get()==0;
    }

    private boolean isFull(){
        return size.get()== array.length;
    }

    @Override
    public void offer(E e) throws InterruptedException {
        tailLock.lockInterruptibly();
        int c;//添加前元素个数
        try {
            //1.队列满则等待阻塞
            while(isFull()){
                tailWaits.await();
            }
            //2.队列不满则加入
            array[tail]=e;
            if(++tail== array.length){
                tail=0;
            }

            //3.修改size
            c=size.getAndIncrement();
            //不满，唤醒offer线程准备加入
            if(c+1< array.length){
                tailWaits.signal();
            }

        }finally {
            tailLock.unlock();
        }

        //headLock与headWaits必须要配对使用,唤醒poll线程
        //准备从0到非空的过程，准备poll线程删除
        if(c==0){
            headLock.lock();
            try{
                headWaits.signal();
            }finally {
                headLock.unlock();
            }
        }


    }

    @Override
    public boolean offer(E e, long timeout) throws InterruptedException {
        return false;
    }

    @Override
    public E poll() throws InterruptedException {
        E e;
        int c;//减少前元素个数
        headLock.lockInterruptibly();
        try{
            //1.队列为空则等待
            while (isEmpty()){
                headWaits.await();
            }

            //2.非空队列出队
            e=array[head];
            array[head]=null;//垃圾回收
            if(++head== array.length){
                head=0;
            }
            //3.size--
            c=size.getAndDecrement();
            //元素非空
            if(c>1){
                headWaits.signal();
            }

        }finally {
            headLock.unlock();
        }
        //队列从满到不满才会唤醒offer线程
        if(c== array.length){
            tailLock.lock();
            try {
                tailWaits.signal();
            }finally {
                tailLock.unlock();
        }

        }
        return e;
    }
}
